module mculib.baremetal.malloc;

extern(C){
    extern __gshared void* __heap_start__,__heap_end__;
}

private
{
    /// 可用内存总量
    enum MEMORY_SIZE = 256;
    /// 内存表
    //__gshared ubyte[MEMORY_SIZE] memtable;
    //__gshared static membuffer = MemBuffer!(MEMORY_SIZE);

    /// 位域置位
    void bfts(size_t* p,in size_t bitx,in size_t width)
    {
        import core.bitop;
        for(size_t i=bitx; i < bitx + width; i++)
        {
            p.bts(i);
        }
    }
    /// 位域重置
    void bftr(size_t* p,in size_t bitx,in size_t width)
    {
        import core.bitop;
        for(size_t i=bitx; i < bitx + width; i++)
        {
            p.btr(i);
        }
    }
    /// 位域测试,返回true/false
    bool bft(size_t* p,in size_t bitx,in size_t width)
    {
        import core.bitop;
        for(size_t i=bitx; i < bitx + width; i++)
        {
            if(p.bt(i)) return true;
        }
        return false;
    }

    /**
    * 可管理缓冲区应为 `size_t.sizeof * 8`的倍数.
    */
    struct MemBuffer(size_t size)
    {
        import core.bitop;
        import mculib.baremetal.stdlib;
        
        /// 实际大小 2字节对齐
        enum asize = ((size & 1)? size + 1: size)/2;

        //enum isize = (asize / size_t.sizeof * 8);
        enum isize = (asize % (size_t.sizeof * 8)) ?  (asize / (size_t.sizeof * 8)) + 1: (asize / (size_t.sizeof * 8));
        /// 使用标记
        size_t[isize] used;
        /// 缓冲区
        ushort[asize] buffer;

        /**
        * 未考虑释放内存
        */
        void* malloc(size_t n)
        in(n+1 <= ubyte.max)    // 申请的内存大小不能超过1字节可表达长度
        out(r;r !is null)
        {
            /// 增加一个字节申请标记,记录当前申请的长度信息
            ++n;
            /// 对齐申请地址 2字节对齐
            if( n & 1) n = n + 1;
            /// 确认申请的内存大小  
            if( n > size) return null;
            // 匹配buff类型大小
            n /=2;
            /// 申请内存,循环擦找used表,找到空闲内存
            int tpos=-1;
            for(size_t i;i<asize;i++)
            {
                if(bt(&used[0],i) ==0) 
                {
                    if(tpos < 0 ) tpos = i;
                    if(i - tpos == n) break;

                }else{
                    tpos = -1;
                }
            }
            // 超出边界
            if(tpos + n > asize) return null;
            // 标记内存已使用
            bfts(&used[0],tpos,n);
            // 清空内存
            memset(&buffer[tpos],0,n);
            // 写当前长度到首字节
            auto ret = cast(ubyte*)(&buffer[tpos]);

            *ret = cast(ubyte)n;
            // 返回内存地址,偏移一个字节
            return (++ret);
          
        }
        /// 初始化
        void init()
        {
            /// 初始化内存表
            used[] = 0;
        }
        /// 释放内存
        void free(void* p)
        {
            /// 转为ubyt指针
            auto ptr = cast(ubyte*)p;
            /// 获取内存长度
            auto n = *--ptr;
            /// 获取索引地址
            size_t idx = (cast(size_t)ptr - cast(size_t)&buffer[0]) / 2;
            // 标记内存未使用
            bftr(&used[0],idx,n);
        }
    }
}

alias Memory = MemBuffer!512;
__gshared Memory membuffer;

extern(C){
    void* malloc(size_t n) =>membuffer.malloc(n);
    void free(void* p) => membuffer.free(p);

}


